package stone926.mods.more_enchantments.mixins;

import net.minecraft.entity.EntityType;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.entity.mob.ElderGuardianEntity;
import net.minecraft.entity.mob.GuardianEntity;
import net.minecraft.entity.mob.HostileEntity;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import stone926.mods.more_enchantments.MoreEnchantmentsMod;
import stone926.mods.more_enchantments.interfaces.IEntitySpawnedByFlower;
import stone926.mods.more_enchantments.interfaces.IGuardianEntity;
import stone926.mods.more_enchantments.nbt.CustomNbtKeys;

@Mixin(GuardianEntity.class)
public class GuardianEntityMixin extends HostileEntity implements IGuardianEntity {

  @Unique private int warmUpTime = 80;
  @Unique private boolean warmUpTimeChanged = false;

  protected GuardianEntityMixin(EntityType<? extends HostileEntity> entityType, World world) {
    super(entityType, world);
  }

  @Override
  public void setWarmupTime(int warmUpTime) {
    if (warmUpTime <= 0) throw new IllegalArgumentException("warm up time of guardian must be POSITIVE");
    this.warmUpTime = warmUpTime;
    warmUpTimeChanged = true;
  }

  @Override
  public boolean warmupTimeChanged() {
    return warmUpTimeChanged;
  }

  @Inject(method = "getWarmupTime", at = @At("HEAD"), cancellable = true)
  private void getWarmupTime(CallbackInfoReturnable<Integer> cir) {
    if (warmUpTimeChanged) cir.setReturnValue(warmUpTime);
  }

  @SuppressWarnings("all")
  @Mixin(MobEntity.class)
  private static class MobEntityMixin {

    @Inject(method = "readCustomDataFromNbt", at = @At("HEAD"))
    private void readCustomDataFromNbt(NbtCompound nbt, CallbackInfo ci) {
      if ((MobEntity) (Object) this instanceof GuardianEntity guardian) {
        if (nbt.contains(CustomNbtKeys.GUARDIAN.WARMUP_TIME)) ((IGuardianEntity) guardian).setWarmupTime(nbt.getInt(CustomNbtKeys.GUARDIAN.WARMUP_TIME));
      }
    }

    @Inject(method = "writeCustomDataToNbt", at = @At("HEAD"))
    private void writeCustomDataToNbt(NbtCompound nbt, CallbackInfo ci) {
      if ((MobEntity) (Object) this instanceof GuardianEntity guardian) {
        if (((IGuardianEntity) guardian).warmupTimeChanged()) nbt.putInt(CustomNbtKeys.GUARDIAN.WARMUP_TIME, guardian.getWarmupTime());
      }
    }

  }

  @Mixin(ElderGuardianEntity.class)
  private static class ElderGuardianEntityMixin extends HostileEntity implements IGuardianEntity {

    @Unique private int warmUpTime = 80;
    @Unique private boolean warmUpTimeChanged = false;

    protected ElderGuardianEntityMixin(EntityType<? extends HostileEntity> entityType, World world) {
      super(entityType, world);
    }

    @Override
    public void setWarmupTime(int warmUpTime) {
      if (warmUpTime <= 0) throw new IllegalArgumentException("warm up time of guardian must be POSITIVE");
      this.warmUpTime = warmUpTime;
      warmUpTimeChanged = true;
    }

    @Override
    public boolean warmupTimeChanged() {
      return warmUpTimeChanged;
    }

    @Inject(method = "getWarmupTime", at = @At("HEAD"), cancellable = true)
    private void getWarmupTime(CallbackInfoReturnable<Integer> cir) {
      if (warmUpTimeChanged) cir.setReturnValue(warmUpTime);
    }

    @Inject(method = "mobTick", at = @At("RETURN"))
    private void mobTick(CallbackInfo ci) {
      if (world instanceof ServerWorld server && (age + getId()) % 3000 == 0 && ((IEntitySpawnedByFlower) this).isSpawnedByMandala()) {
        server.getPlayers((player) -> this.squaredDistanceTo(player) < 3000D && player.hasStatusEffect(StatusEffects.WATER_BREATHING)).forEach(player -> {
          player.removeStatusEffect(StatusEffects.WATER_BREATHING);
          server.spawnParticles(MoreEnchantmentsMod.WATER_BREATHING_REMOVED, player.getX(), player.getY(), player.getZ(), 5, 0, 0, 0, 0);
        });
      }
    }

  }

}
